/********************************************************************************
 * Copyright (c) 2011-2017 Red Hat Inc. and/or its affiliates and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 1.0 which is available at
 * http://www.eclipse.org/legal/epl-v10.html.
 *
 * SPDX-License-Identifier: EPL-1.0
 ********************************************************************************/
package org.eclipse.ceylon.ide.eclipse.code.refactor;
//
//import static org.eclipse.ceylon.ide.eclipse.code.correct.ImportProposals.importProposals;
//import static org.eclipse.ceylon.ide.eclipse.util.EditorUtil.getDocument;
//import static org.eclipse.ceylon.ide.eclipse.util.Indents.indents;
//import static org.eclipse.ceylon.ide.eclipse.util.Nodes.findStatement;
//import static org.eclipse.ltk.core.refactoring.RefactoringStatus.createWarningStatus;
//
//import java.util.HashSet;
//import java.util.List;
//
//import org.eclipse.core.runtime.CoreException;
//import org.eclipse.core.runtime.IProgressMonitor;
//import org.eclipse.core.runtime.OperationCanceledException;
//import org.eclipse.jface.text.IDocument;
//import org.eclipse.jface.text.IRegion;
//import org.eclipse.jface.text.Region;
//import org.eclipse.ltk.core.refactoring.RefactoringStatus;
//import org.eclipse.ltk.core.refactoring.TextChange;
//import org.eclipse.text.edits.DeleteEdit;
//import org.eclipse.text.edits.InsertEdit;
//import org.eclipse.text.edits.MultiTextEdit;
//import org.eclipse.text.edits.ReplaceEdit;
//import org.eclipse.ui.IEditorPart;
//
//import org.eclipse.ceylon.compiler.typechecker.tree.Node;
//import org.eclipse.ceylon.compiler.typechecker.tree.Tree;
//import org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement;
//import org.eclipse.ceylon.compiler.typechecker.tree.Visitor;
//import org.eclipse.ceylon.ide.eclipse.util.EditorUtil;
//import org.eclipse.ceylon.ide.eclipse.util.Nodes;
//import org.eclipse.ceylon.ide.common.refactoring.ExtractLinkedModeEnabled;
//import org.eclipse.ceylon.model.typechecker.model.Declaration;
//import org.eclipse.ceylon.model.typechecker.model.Type;
//import org.eclipse.ceylon.model.typechecker.model.Unit;
//
//public class ExtractValueRefactoring extends AbstractRefactoring implements ExtractLinkedModeEnabled<IRegion> {
//    
//    private final class FindAnonFunctionVisitor extends Visitor {
//        private final Statement statement;
//        Tree.FunctionArgument result;
//
//        private FindAnonFunctionVisitor(Statement statement) {
//            this.statement = statement;
//        }
//
//        @Override
//        public void visit(Tree.FunctionArgument that) {
//            if (that!=node &&
//                    that.getStartIndex()<=node.getStartIndex() &&
//                    that.getEndIndex()>=node.getEndIndex() &&
//                    that.getStartIndex()>statement.getStartIndex()) {
//                result = that;
//            }
//            super.visit(that);
//        }
//    }
//
//    private String newName;
//    private boolean explicitType;
//    private boolean getter;
//    private Type type;
//    private boolean canBeInferred;
//    
//    public ExtractValueRefactoring(IEditorPart editor) {
//        super(editor);
//        newName = Nodes.nameProposals(node)[0];
//    }
//    
//    @Override
//    public boolean getEnabled() {
//        return sourceFile!=null &&
//                getEditable() &&
//                !sourceFile.getName()
//                    .equals("module.ceylon") &&
//                !sourceFile.getName()
//                    .equals("package.ceylon") &&
//                node instanceof Tree.Term;
//    }
//
//    public String getName() {
//        return "Extract Value";
//    }
//
//    public boolean forceWizardMode() {
//        Declaration existing =
//                node.getScope()
//                    .getMemberOrParameter(node.getUnit(),
//                            newName, null, false);
//        return existing!=null;
//    }
//    
//    public RefactoringStatus checkInitialConditions
//            (IProgressMonitor pm)
//                    throws CoreException,
//                           OperationCanceledException {
//        // Check parameters retrieved from editor context
//        return new RefactoringStatus();
//    }
//
//    public RefactoringStatus checkFinalConditions
//            (IProgressMonitor pm)
//                    throws CoreException,
//                           OperationCanceledException {
//        Declaration existing =
//                node.getScope()
//                    .getMemberOrParameter(node.getUnit(),
//                            newName, null, false);
//        if (null!=existing) {
//            return createWarningStatus(
//                    "An existing declaration named '" +
//                    newName +
//                    "' already exists in the same scope");
//        }
//        return new RefactoringStatus();
//    }
//
//    public TextChange createChange(IProgressMonitor pm) 
//    		throws CoreException, OperationCanceledException {
//        TextChange tfc = newLocalChange();
//        extractInFile(tfc);
//        return tfc;
//    }
//    
//    private IRegion typeRegion;
//    public IRegion getTypeRegion() {
//        return typeRegion;
//    }
//    public void setTypeRegion(IRegion typeRegion) {
//        this.typeRegion = typeRegion;
//    }
//
//    private IRegion decRegion;
//    public IRegion getDecRegion() {
//        return decRegion;
//    }
//    public void setDecRegion(IRegion decRegion) {
//        this.decRegion = decRegion;
//    }
//
//    private IRegion refRegion;
//    public IRegion getRefRegion() {
//        return refRegion;
//    }
//    public void setRefRegion(IRegion refRegion) {
//        this.refRegion = refRegion;
//    }
//
//
//    public void extractInFile(TextChange tfc) {
//        tfc.setEdit(new MultiTextEdit());
//        IDocument doc = EditorUtil.getDocument(tfc);
//        Unit unit = node.getUnit();
//        Tree.Term term = (Tree.Term) node;
//        final Tree.Statement statement =
//                findStatement(rootNode, node);
//        int start = statement.getStartIndex();
//        int il = 0;
//        String newLineOrReturn =
//                indents().getDefaultLineDelimiter(doc) +
//                indents().getIndent(statement, doc);
//        FindAnonFunctionVisitor visitor =
//                new FindAnonFunctionVisitor(statement);
//        visitor.visit(statement);
//        Tree.FunctionArgument anon = visitor.result;
//        boolean toplevel;
//        if (anon!=null && anon.getBlock()==null) {
//            Tree.Expression ex = anon.getExpression();
//            if (ex!=null) {
//                List<Tree.ParameterList> pls =
//                        anon.getParameterLists();
//                Node pl =
//                        pls.get(pls.size()-1);
//                if (anon.getTypeConstraintList()!=null) {
//                    pl = anon.getTypeConstraintList();
//                }
//                start = ex.getStartIndex();
//                int loc = pl.getEndIndex();
//                int len = ex.getStartIndex() - loc;
//                int end = ex.getEndIndex();
//                tfc.addEdit(new ReplaceEdit(loc, len, " { "));
//                tfc.addEdit(new InsertEdit(end, "; }"));
//                il-=len-3;
//                if (anon.getDeclarationModel().isDeclaredVoid()) {
//                    newLineOrReturn = " ";
//                }
//                else {
//                    newLineOrReturn = " return ";
//                }
//                toplevel = false;
//            }
//            else {
//                return;
//            }
//        }
//        else if (statement instanceof Tree.Declaration) {
//            Tree.Declaration dec =
//                    (Tree.Declaration) statement;
//            if (dec instanceof Tree.MethodDeclaration) {
//                Tree.MethodDeclaration md =
//                        (Tree.MethodDeclaration) dec;
//                Tree.SpecifierExpression se =
//                        md.getSpecifierExpression();
//                if (se!=null) {
//                    Tree.Expression ex = se.getExpression();
//                    if (ex!=null) {
//                        List<Tree.ParameterList> pls =
//                                md.getParameterLists();
//                        Node pl = pls.get(pls.size()-1);
//                        if (md.getTypeConstraintList()!=null) {
//                            pl = md.getTypeConstraintList();
//                        }
//                        start = ex.getStartIndex();
//                        int loc = pl.getEndIndex();
//                        int len = ex.getStartIndex() - loc;
//                        int end = ex.getEndIndex();
//                        int semi = dec.getEndIndex()-1;
//                        String indent = indents().getDefaultIndent();
//                        String starting = " {" + newLineOrReturn + indent;
//                        String ending = ";" + newLineOrReturn + "}";
//                        tfc.addEdit(new ReplaceEdit(loc, len, starting));
//                        tfc.addEdit(new InsertEdit(end, ending));
//                        tfc.addEdit(new DeleteEdit(semi, 1));
//                        il-=len-starting.length();
//                        newLineOrReturn = newLineOrReturn + indent;
//                        if (!md.getDeclarationModel().isDeclaredVoid()) {
//                            newLineOrReturn += "return ";
//                        }
//                    }
//                }
//                toplevel = false;
//            }
//            else {
//                toplevel = dec.getDeclarationModel().isToplevel();
//            }
//        }
//        else {
//            toplevel = false;
//        }
//        type = unit.denotableType(term.getTypeModel());
//        Tree.Term unparened = unparenthesize(term);
//        String exp;
//        boolean anonFunction = 
//                unparened instanceof Tree.FunctionArgument;
//        String mod;
//        if (anonFunction) {
//            type = unit.getCallableReturnType(type);
//            Tree.FunctionArgument fa = 
//                    (Tree.FunctionArgument)
//                        unparened;
//            StringBuilder sb = new StringBuilder();
//            if (fa.getType() instanceof Tree.VoidModifier) {
//                mod = "void ";
//            }
//            else {
//                mod = "function";
//            }
//            Nodes.appendParameters(sb, fa, unit, tokens);
//            if (fa.getBlock()!=null) {
//                sb.append(" ")
//                  .append(toString(fa.getBlock()));
//            }
//            else if (fa.getExpression()!=null) {
//                sb.append(" => ")
//                  .append(toString(fa.getExpression()))
//                  .append(";");
//            }
//            else {
//                sb.append(" => ");
//            }
//            exp = sb.toString();
//        }
//        else {
//            mod = "value";
//        	exp = toString(unparened) + ";";
//        }
//        String typeDec;
//        if (type==null || type.isUnknown()) {
//            typeDec = "dynamic";
//        }
//        else if (explicitType || toplevel) {
//            typeDec = type.asSourceCodeString(unit);
//            HashSet<Declaration> decs =
//                    new HashSet<Declaration>();
//            importProposals().importType(decs, type, rootNode);
//            il += importProposals().applyImports(tfc, decs, rootNode, doc);
//        }
//        else {
//            canBeInferred = true;
//            typeDec = mod;
//        }
//        String dec = 
//        		typeDec + " " +  newName + 
//        		(anonFunction ? "" : (getter ? " => "  : " = ")) + 
//        		exp;
//        
//        String text = dec + newLineOrReturn;
//        int tlength = typeDec.length();
//        int nstart = node.getStartIndex();
//        int nlength = node.getDistance();
//        tfc.addEdit(new InsertEdit(start, text));
//        tfc.addEdit(new ReplaceEdit(nstart, nlength, newName));
//        typeRegion = new Region(start+il, tlength);
//        int len = newName.length();
//        decRegion = new Region(start+il+tlength+1, len);
//        refRegion = new Region(nstart+il+text.length(), len);
//    }
//    
//    public boolean canBeInferred() {
//        return canBeInferred;
//    }
//
//    public void setNewName(String text) {
//        newName = text;
//    }
//    
//    public String getNewName() {
//        return newName;
//    }
//    
//    public void setExplicitType() {
//        this.explicitType = !explicitType;
//    }
//    
//    public void setGetter() {
//        this.getter = !getter;
//    }
//
//    Type getType() {
//        return type;
//    }
//    
//	public String[] getNameProposals() {
//		return Nodes.nameProposals(node);
//	}
//	
//	public boolean isFunction() {
//		return node instanceof Tree.FunctionArgument;
//	}
//
//    @Override
//    public IRegion newRegion(long start, long length) {
//        return new Region((int) start, (int) length);
//    }
//}
